package com.baidu.iit.pxp.entity;

import com.baidu.iit.pvm.ActivityException;
import com.baidu.iit.pvm.delegate.DelegateExecution;
import com.baidu.iit.pvm.delegate.DelegateInvocation;
import com.baidu.iit.pxp.delegate.Task;
import com.baidu.iit.pxp.invocation.TaskListenerInvocation;
import com.baidu.iit.pxp.listener.TaskListener;
import com.baidu.iit.pxp.model.DelegateTask;
import com.baidu.iit.pxp.model.TaskDefinition;

import java.io.Serializable;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * User: huangweili
 * Date: 14-4-28
 * Time: 下午4:12
 */
public class TaskEntity extends VariableScopeImpl implements Task, DelegateTask, Serializable {


    protected String parentTaskId;

    protected String name;
    protected String description;
    protected Date createTime;
    protected String category;

    protected boolean isIdentityLinksInitialized = false;

    protected String executionId;
    protected ExecutionEntity execution;

    protected String processInstanceId;
    protected ExecutionEntity processInstance;

    protected String processDefinitionId;

    protected TaskDefinition taskDefinition;
    protected String taskDefinitionKey;

    protected boolean isDeleted;

    protected String eventName;


    public TaskEntity() {
    }

    public TaskEntity(String taskId) {
        this.id = taskId;
    }


    public static TaskEntity create(Date createTime) {
        TaskEntity task = new TaskEntity();
        task.isIdentityLinksInitialized = true;
        task.createTime = createTime;
        return task;
    }

    public void complete() {
        fireEvent(TaskListener.EVENTNAME_COMPLETE);
        if (executionId != null) {
            ExecutionEntity execution = getExecution();
            execution.signal(null, null);
        }
    }


    @Override
    protected List<VariableInstanceEntity> loadVariableInstances() {
        return null;  //TODO
    }

    @Override
    protected VariableScopeImpl getParentVariableScope() {
        if (getExecution() != null) {
            return execution;
        }
        return null;
    }

    @Override
    protected void initializeVariableInstanceBackPointer(VariableInstanceEntity variableInstance) {
        variableInstance.setTaskId(id);
        variableInstance.setExecutionId(executionId);
        variableInstance.setProcessInstanceId(processInstanceId);
    }


    @Override
    protected VariableInstanceEntity createVariableInstance(String variableName, Object value,
                                                            ExecutionEntity sourceActivityExecution) {
        VariableInstanceEntity result = super.createVariableInstance(variableName, value, sourceActivityExecution);
        return result;
    }

    @Override
    protected void updateVariableInstance(VariableInstanceEntity variableInstance, Object value,
                                          ExecutionEntity sourceActivityExecution) {
        super.updateVariableInstance(variableInstance, value, sourceActivityExecution);
    }


    public ExecutionEntity getExecution() {
        return execution;
    }

    public void setExecution(DelegateExecution execution) {
        if (execution != null) {
            this.execution = (ExecutionEntity) execution;
            this.executionId = this.execution.getId();
            this.processInstanceId = this.execution.getProcessInstanceId();
            this.processDefinitionId = this.execution.getProcessDefinitionId();

        } else {
            this.execution = null;
            this.executionId = null;
            this.processInstanceId = null;
            this.processDefinitionId = null;
        }
    }


    public Map<String, Object> getActivityInstanceVariables() {
        if (execution != null) {
            return execution.getVariables();
        }
        return Collections.EMPTY_MAP;
    }

    public void setExecutionVariables(Map<String, Object> parameters) {
        if (getExecution() != null) {
            execution.setVariables(parameters);
        }
    }

    public String toString() {
        return "Task[id=" + id + ", name=" + name + "]";
    }

    public void setName(String taskName) {
        this.name = taskName;
    }


    public void setDescription(String description) {
        this.description = description;

    }


    public void setCategory(String category) {
        this.category = category;
    }



    public void setParentTaskId(String parentTaskId) {
        this.parentTaskId = parentTaskId;
    }


    public void fireEvent(String taskEventName) {
        TaskDefinition taskDefinition = getTaskDefinition();
        if (taskDefinition != null) {
            List<TaskListener> taskEventListeners = getTaskDefinition().getTaskListener(taskEventName);
            if (taskEventListeners != null) {
                for (TaskListener taskListener : taskEventListeners) {
                    ExecutionEntity execution = getExecution();
                    if (execution != null) {
                        setEventName(taskEventName);
                    }
                    try {
                        DelegateInvocation invocation = new TaskListenerInvocation(taskListener, (DelegateTask) this);
                    } catch (Exception e) {
                        throw new ActivityException("Exception while invoking TaskListener: " + e.getMessage(), e);
                    }
                }
            }
        }
    }


    public void setTaskDefinition(TaskDefinition taskDefinition) {
        this.taskDefinition = taskDefinition;
        this.taskDefinitionKey = taskDefinition.getKey();
    }

    public TaskDefinition getTaskDefinition() {


        return taskDefinition;
    }


    public String getName() {
        return name;
    }

    public String getDescription() {
        return description;
    }


    public String getExecutionId() {
        return executionId;
    }

    public String getProcessInstanceId() {
        return processInstanceId;
    }

    public String getProcessDefinitionId() {
        return processDefinitionId;
    }


    @Override
    public String getTaskDefinitionKey() {
        return null;  //TODO
    }

    public void setProcessDefinitionId(String processDefinitionId) {
        this.processDefinitionId = processDefinitionId;
    }


    public String getEventName() {
        return eventName;
    }

    public void setEventName(String eventName) {
        this.eventName = eventName;
    }

    public void setExecutionId(String executionId) {
        this.executionId = executionId;
    }


    public ExecutionEntity getProcessInstance() {
        return processInstance;
    }

    public void setProcessInstance(ExecutionEntity processInstance) {
        this.processInstance = processInstance;
    }

    public void setExecution(ExecutionEntity execution) {
        this.execution = execution;
    }

    public void setProcessInstanceId(String processInstanceId) {
        this.processInstanceId = processInstanceId;
    }


    public String getParentTaskId() {
        return parentTaskId;
    }

    public Map<String, VariableInstanceEntity> getVariableInstances() {
        ensureVariableInstancesInitialized();
        return variableInstances;
    }

    public String getCategory() {
        return category;
    }
}
